// ignore_for_file: depend_on_referenced_packages

import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_2b_client/Root.dart';
import 'package:go_router/go_router.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:shared_preferences/shared_preferences.dart';


class HeaderAuthorizationInterceptor extends Interceptor {
  @override
  Future<void> onRequest(
      RequestOptions options, RequestInterceptorHandler handler) async {
    var sharedPreferences = await SharedPreferences.getInstance();
    sharedPreferences.reload();
    var authorizationHeader =
        sharedPreferences.getString(HttpHeaders.authorizationHeader);
    if (authorizationHeader != null) {
      options.headers[HttpHeaders.authorizationHeader] = authorizationHeader;
    }
    super.onRequest(options, handler);
  }
}

class ResponseErrorInterceptor extends Interceptor {
  @override
  void onError(DioException err, ErrorInterceptorHandler handler) {
    debugPrint(err.toString());
    debugPrint(err.response?.data?.toString());
    if (err.type == DioExceptionType.badResponse) {
      if (err.response != null) {
        var response = err.response!;
        Map<String, dynamic>? data;
        try {
          data = response.data as Map<String, dynamic>;
        } catch (e) {
          data = null;
        }

        var problemDetail = data == null
            ? null
            : ProblemDetail(
                status: data["status"] as int,
                detail: (data["detail"] ?? data["message"] ?? data["error"])
                    as String?,
                instance: data["instance"] as String?,
                type: data["type"] as String?,
                title: data["title"] as String?,
              );
        final statusCode = response.statusCode ?? problemDetail?.status;
        if ((statusCode == 401 || statusCode == 403)) {
          final context = rootGoRouterKey.currentContext;
          if (context?.mounted == true) {
            context?.go("/logIn");
          }
        } else if (statusCode == 400) {}
        handler.reject(DioException(
          requestOptions: err.requestOptions,
          response: Response(
            requestOptions: response.requestOptions,
            headers: response.headers,
            data: problemDetail,
            statusCode: response.statusCode,
            isRedirect: response.isRedirect,
            statusMessage: response.statusMessage,
            redirects: response.redirects,
            extra: response.extra,
          ),
        ));
      } else {
        handler.reject(err);
      }
    } else {
      handler.reject(err);
    }
  }

  ResponseErrorInterceptor();
}

class ProblemDetail {
  final int status;
  final String? detail;
  final String? instance;
  final String? type;
  final String? title;

  ProblemDetail(
      {required this.status,
      required this.detail,
      required this.instance,
      required this.type,
      required this.title});

  static handlerDioError(
      DioError error, Function(ProblemDetail errorAttributes) handler) {
    var response = error.response;
    if (response != null) {
      var data = response.data;
      if (data is ProblemDetail) {
        handler(data);
      }
    }
  }
}

class HeaderClientVersionInterceptor extends Interceptor {
  @override
  Future<void> onRequest(
      RequestOptions options, RequestInterceptorHandler handler) async {
    var packageInfo = await PackageInfo.fromPlatform();
    options.headers["client-version"] = packageInfo.version;
    super.onRequest(options, handler);
  }
}

class RequestParameterHandlerInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    final parameters = {...options.queryParameters};
    parameters.removeWhere((key, value) {
      if (value == null) {
        return true;
      } else if (value is List) {
        return value.isEmpty;
      } else {
        return false;
      }
    });
    options.queryParameters = parameters;
    super.onRequest(options, handler);
  }
}

final dio = Dio()
  ..interceptors.add(RequestParameterHandlerInterceptor())
  ..interceptors.add(HeaderAuthorizationInterceptor())
  ..interceptors.add(ResponseErrorInterceptor())
  ..interceptors.add(LogInterceptor())
  ..interceptors.add(HeaderClientVersionInterceptor())
  ..interceptors.insert(0, InterceptorsWrapper(
    onRequest: (
        RequestOptions options,
        RequestInterceptorHandler handler,
        ) {
      if (options.contentType == null) {
        final dynamic data = options.data;
        final String? contentType;
        if (data is FormData) {
          contentType = Headers.multipartFormDataContentType;
        }
        /*else if (data is Map) {
          contentType = Headers.formUrlEncodedContentType;
        } */
        else if (data != null) {
          contentType = Headers.jsonContentType;
        } else {
          contentType = null;
        }
        options.contentType = contentType;
      }
      handler.next(options);
    },
  ));

const baseUrl = String.fromEnvironment("SERVER_URL");

